package cn.eonshine.cuba.inf.modular.quartz.service.impl;

import java.util.Calendar;
import java.util.List;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.eonshine.cuba.inf.common.util.DateUtils;
import cn.eonshine.cuba.inf.modular.quartz.config.ConfigEnum;
import cn.eonshine.cuba.inf.modular.quartz.config.QuartzJobFactory;
import cn.eonshine.cuba.inf.modular.quartz.entity.Config;
import cn.eonshine.cuba.inf.modular.quartz.mapper.ConfigMapper;
import cn.eonshine.cuba.inf.modular.quartz.service.IQuartzTableService;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

@Service
@Transactional
public class QuartzTableServiceImpl extends ServiceImpl<ConfigMapper, Config> implements IQuartzTableService {
	
	private static final Log log = LogFactory.get();
	
    @Autowired
    SchedulerFactoryBean schedulerFactoryBean;
    
    @Override
	public List<Config> getAllJobs() {
		return list(new QueryWrapper<Config>());
	}
	/* (non-Javadoc)
	 * @see cn.eonshine.cuba.inf.modular.inf.quartz.service.impl.IQuartzTableService#update(java.lang.Long, java.lang.String)
	 */
    @Override
	public boolean update(String id, String status, String idUpdator) throws Exception {
        //判断是否有此ID的数据
        Config config = getById(id);
        if (config==null){
            new RuntimeException("未找到此定时任务");
        }
        if (ConfigEnum.STATUS_STOP.getCode().equals(status)){
            // stop 禁用
            config.setStatus(ConfigEnum.STATUS_STOP.getCode());
            deleteJob(config);
        }else{
            //start 启用
            config.setStatus(ConfigEnum.STATUS_START.getCode());
            addJob(config);
        }
        
        Config conf = new Config();
        conf.setStatus(config.getStatus());
        conf.setId(config.getId());
        conf.setUpdateBy(idUpdator);
        conf.setUpdateDate(DateUtils.getCubaDate(Calendar.getInstance().getTime()));
        return updateById(conf);
    }
    /* (non-Javadoc)
	 * @see cn.eonshine.cuba.inf.modular.inf.quartz.service.impl.IQuartzTableService#startJobs()
	 */
    @Override
	public  void startJobs(){
        List<Config> configList = list(new QueryWrapper<Config>());
        for (Config config : configList) {
            if (ConfigEnum.STATUS_START.getCode().equals(config.getStatus())){
                try {
                    addJob(config);
                } catch (SchedulerException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /* (non-Javadoc)
	 * @see cn.eonshine.cuba.inf.modular.inf.quartz.service.impl.IQuartzTableService#updateCron(java.lang.Long, java.lang.String)
	 */
    @Override
	public void updateCron(String id, String cronSchedule) {
       Config conf = new Config();
       conf.setCron(cronSchedule);
       conf.setId(id);
       boolean i = updateById(conf);
       
       if (!i){
            throw  new RuntimeException("500!");
       }
    }



    /**
     * 增加任务
     * 
     * @param config
     * @throws SchedulerException
     */
    private void addJob(Config config) throws SchedulerException {
        //得到调度器
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = this.getJobKey(config);
        //获得触发器
        TriggerKey triggerKey = TriggerKey.triggerKey(config.getName(), config.getGroupName());
        CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey);
        //判断触发器是否存在（如果存在说明之前运行过但是在当前被禁用了，如果不存在说明一次都没运行过）
        if (trigger == null){
            //新建一个工作任务 指定任务类型为串接进行的
            JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class).withIdentity(jobKey).build();
            //将工作添加到工作任务当中去
            jobDetail.getJobDataMap().put(QuartzJobFactory.SCHEDULEJOBKEY,config);
            //将cron表达式进行转换
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(config.getCron());
            //创建触发器并将cron表达式对象给塞入
            trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
            //在调度器中将触发器和任务进行组合
            scheduler.scheduleJob(jobDetail,trigger);
        }else{
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(config.getCron());
            //按照新的规则进行
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
            //重启
            scheduler.rescheduleJob(triggerKey,trigger);
        }
    }

    public boolean pauseJob(Config config) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = this.getJobKey(config);
    	// TriggerKey : name + group
    	TriggerKey triggerKey = TriggerKey.triggerKey(config.getName(), config.getGroupName());
    	
        boolean result = false;
        if (scheduler.checkExists(jobKey)) {
            scheduler.pauseTrigger(triggerKey);
            result = true;
            log.info(">>>>>>>>>>> pauseJob success, triggerKey:{}", triggerKey);
        } else {
        	log.info(">>>>>>>>>>> pauseJob fail, triggerKey:{}", triggerKey);
        }
        return result;
    }
    
    public boolean resumeJob(Config config) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = this.getJobKey(config);
    	// TriggerKey : name + group
    	TriggerKey triggerKey = TriggerKey.triggerKey(config.getName(), config.getGroupName());
        
        boolean result = false;
        if (scheduler.checkExists(jobKey)) {
            scheduler.resumeTrigger(triggerKey);
            result = true;
            log.info(">>>>>>>>>>> resumeJob success, triggerKey:{}", triggerKey);
        } else {
        	log.info(">>>>>>>>>>> resumeJob fail, triggerKey:{}", triggerKey);
        }
        return result;
    }
    
    /**
     *删除任务
     *
     * @param : com.study.www.model.config
     * @Date: 2018/2/24 18:23
     * @return: void
     */
    private void deleteJob(Config config) throws SchedulerException {
        //得到调度器
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        //找到key值
        JobKey jobKey = this.getJobKey(config);
        //从触发器找到此任务然后进行删除
        scheduler.deleteJob(jobKey);
    }

    /**
     * 根据name和group得到任务的key
     *
     * @param :com.study.www.model.config
     * @Date: 2018/2/24 18:27
     * @return: org.quartz.JobKey
     */
    private JobKey getJobKey(Config config){
        return getJobKey(config.getName(),config.getGroupName());
    }

    private JobKey getJobKey(String name, String group) {
        return JobKey.jobKey(name,group);
    }

}
